import { WsOptions, WebSocketType } from './index.d'

export const ToSystem = 'system' // 系统消息
export const ToGlobal = 'global' // 广播消息

export const TypeJoin = "join"     // 加入房间
export const TypeLeave = "leave"    // 离开房间
export const TypeRegister = "register" // 注册客户端身份

export const TypeRoom = "room"     // 房间类消息
export const TypePersonal = "personal" // 个人类消息
export const TypeGroup = "group" // 用户组类消息

export default function LWS(options: WsOptions): WebSocketType {
    if (!window['WebSocket']) {
        throw new Error('Your browser does not support WebSocket')
    }

    // 准备发送数据包
    const preparePayload = function (to: string, type: string, message: string): string {
        return JSON.stringify({
            to: to,
            type: type,
            content: message
        })
    }

    const ws = new WebSocket(options.url, options.schema)

    const onOpen = function (ev: Event) {
        if (options.open) {
            options.open(ev)
        }
    }

    const onClose = function (ev: CloseEvent) {
        if (options.close) {
            options.close(ev)
        }
    }

    const onError = function (ev: Event) {
        if (options.error) {
            options.error(ev)
        }
    }

    const onMessage = function (ev: MessageEvent) {
        if (options.message) {
            const contents = ev.data.split(String.fromCharCode(1))
            contents.forEach((content: string) => {
                options.message(ev, content)
            });
        }
    }

    ws.onopen = onOpen
    ws.onclose = onClose
    ws.onerror = onError
    ws.onmessage = onMessage

    return {
        ws: ws,
        close: function (code?: number, reason?: string) {
            ws.close(code, reason)
        },
        join: function (roomId: string) {
            ws.send(preparePayload(ToSystem, TypeJoin, roomId));
        },
        leave: function (roomId: string) {
            ws.send(preparePayload(ToSystem, TypeLeave, roomId));
        },
        register: function (userId: string) {
            ws.send(preparePayload(ToSystem, TypeRegister, userId));
        },
        send: function (to: string, type: string, message: string) {
            ws.send(preparePayload(to, type, message));
        },
        broadcast: function (message: string) {
            ws.send(preparePayload(ToGlobal, "", message));
        },
        sendRaw: function (message: string) {
            ws.send(message)
        }
    }
}
